home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume20 / deliver2.0 / part02 < prev    next >
Encoding:
Internet Message Format  |  1989-10-15  |  30.5 KB

  1. Subject:  v20i024:  Deliver, flexible email delivery system, Part02/04
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Chip Salzenberg <chip@ateng.com>
  7. Posting-number: Volume 20, Issue 24
  8. Archive-name: deliver2.0/part02
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of shell archive."
  17. # Contents:  config.h context.h deliver.h dest.h patchlevel.h misc.h
  18. #   context.c copymsg.c
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. if test -f 'config.h' -a "${1}" != "-c" ; then 
  21.   echo shar: Will not clobber existing file \"'config.h'\"
  22. else
  23. echo shar: Extracting \"'config.h'\" \(6654 characters\)
  24. sed "s/^X//" >'config.h' <<'END_OF_FILE'
  25. X/* $Header: config.h,v 2.2 89/06/09 13:07:38 network Exp $
  26. X *
  27. X * Deliver configuration.
  28. X *
  29. X * $Log:    config.h,v $
  30. X * Revision 2.2  89/06/09  13:07:38  network
  31. X * Adapt to BSD quirks.
  32. X * 
  33. X * Revision 2.1  89/06/09  12:25:11  network
  34. X * Update RCS revisions.
  35. X * 
  36. X * Revision 1.11  89/06/09  12:23:38  network
  37. X * Baseline for 2.0 release.
  38. X * 
  39. X */
  40. X
  41. X/*----------------------------------------------------------------------
  42. X * SCO Xenix System V compilers define M_SYSV, which implies USG.
  43. X */
  44. X
  45. X#ifdef M_SYSV
  46. X#ifndef USG
  47. X#define USG
  48. X#endif
  49. X#endif
  50. X
  51. X/*----------------------------------------------------------------------
  52. X * Trusted users.
  53. X * Deliver permits "trusted" users to specify delivery filenames
  54. X * without renouncing setuid privileges.  Essentially, these users
  55. X * are given the root password.  Beware!
  56. X */
  57. X
  58. X#define TRUSTED_USERS   "root", "uucp"
  59. X
  60. X/*----------------------------------------------------------------------
  61. X * Signal function type.
  62. X * Signal catching routines have this return value.
  63. X * (For System V Release 3.0 or later, use "void".)
  64. X */
  65. X
  66. X#ifdef USG
  67. X# define SIGTYPE void
  68. X#else
  69. X# define SIGTYPE int
  70. X#endif
  71. X
  72. X/*----------------------------------------------------------------------
  73. X * Signal function declaration.
  74. X * Define this if your <signal.h> doesn't declare signal() correctly.
  75. X */
  76. X
  77. X/* #define DECLARE_SIGNAL */
  78. X
  79. X/*----------------------------------------------------------------------
  80. X * Signal flag type.
  81. X * Variables of this type may be set by signal catching routines.
  82. X */
  83. X
  84. X#ifdef __STDC__
  85. X#define SIGFLAG sig_atomic_t
  86. X#else
  87. X#define SIGFLAG short   /* or "volatile short" for aggressive optimizers */
  88. X#endif
  89. X
  90. X/*----------------------------------------------------------------------
  91. X * Various kinds of mailbox locking.
  92. X * You may define one or both of ML_DOTLOCK and ML_DOTMLK.
  93. X * You may define no more than one of ML_FCNTL, ML_LOCKF and ML_LOCKING.
  94. X *
  95. X * File creation locking:
  96. X *     ML_DOTLOCK   create <mailbox>.lock       (most systems except BSD4.3)
  97. X *     ML_DOTMLK    create /tmp/<basename>.mlk  (Xenix)
  98. X *
  99. X * Kernel record locking:
  100. X *     ML_FCNTL     lock with fcntl(F_SETLKW)   (SVID systems only)
  101. X *     ML_LOCKF     lock with lockf(F_LOCK)     (SVID systems only)
  102. X *     ML_LOCKING   lock with locking(LK_LOCK)  (Xenix systems only)
  103. X */
  104. X
  105. X#ifdef M_XENIX
  106. X#define ML_DOTMLK
  107. X#define ML_LOCKING
  108. X#else
  109. X#define ML_DOTLOCK
  110. X#endif
  111. X
  112. X/*----------------------------------------------------------------------
  113. X * Maximum filename length.
  114. X * Note that this is for _filenames_, not _pathnames_.
  115. X * For AT&T file systems, the usual value is 14.
  116. X * For Berzerkley file systems, use something big like 255.
  117. X */
  118. X
  119. X#ifdef BSD
  120. X#define MAX_NAMESIZE    255
  121. X#else
  122. X#define MAX_NAMESIZE    14
  123. X#endif
  124. X
  125. X/*----------------------------------------------------------------------
  126. X * How to get the host name.
  127. X * Define one.
  128. X *
  129. X * HOSTFILE             file containing name    (Xenix)
  130. X * UNAME                uname()                 (System V)
  131. X * GETHOSTNAME          gethostname()           (BSD)
  132. X * HOSTNAME             host name string        (V7)
  133. X */
  134. X
  135. X#ifdef M_XENIX
  136. X#define HOSTFILE   "/etc/systemid"
  137. X#else
  138. X#ifdef USG
  139. X#define UNAME
  140. X#else
  141. X#ifdef BSD
  142. X#define GETHOSTNAME
  143. X#else
  144. X#define HOSTNAME   "cleese"
  145. X#endif
  146. X#endif
  147. X#endif
  148. X
  149. X/*----------------------------------------------------------------------
  150. X * Is <varargs.h> or <stdarg.h> available?
  151. X */
  152. X
  153. X#ifdef __STDC__
  154. X#define HAS_STDARG
  155. X#else
  156. X#ifdef USG
  157. X#define HAS_VARARGS
  158. X#else
  159. X#ifdef BSD
  160. X#define HAS_VARARGS
  161. X#endif
  162. X#endif
  163. X#endif
  164. X
  165. X/*----------------------------------------------------------------------
  166. X * Are vprintf() and friends available?
  167. X */
  168. X
  169. X#ifdef USG
  170. X#define HAS_VPRINTF
  171. X#endif
  172. X
  173. X/*----------------------------------------------------------------------
  174. X * Is putenv() available?
  175. X */
  176. X
  177. X#ifdef USG
  178. X#define HAS_PUTENV
  179. X#endif
  180. X
  181. X/*----------------------------------------------------------------------
  182. X * Is getopt() available?
  183. X */
  184. X
  185. X#ifdef USG
  186. X#define HAS_GETOPT
  187. X#endif
  188. X
  189. X/*----------------------------------------------------------------------
  190. X * Is setvbuf() backwards?
  191. X * Note: this is true for SCO Xenix Development System 2.2.
  192. X */
  193. X
  194. X/* #define REVERSE_SETVBUF */
  195. X
  196. X/*----------------------------------------------------------------------
  197. X * Name of shell used to execute delivery files.
  198. X */
  199. X
  200. X#define SHELL   "/bin/sh"
  201. X
  202. X/*----------------------------------------------------------------------
  203. X * Characters that may not appear in addresses.
  204. X * (This string should include all metacharacters for your chosen shell.)
  205. X */
  206. X
  207. X#define SANITIZE   "$*?=\\`'\"|^&;{}()<> \t\n"
  208. X
  209. X/*----------------------------------------------------------------------
  210. X * Standard mailbox location.
  211. X *
  212. X * Define either MBX_NAME or MBOX_DIR.
  213. X * If MBX_NAME is defined, then the default mailbox is a file with
  214. X * that name in the user's home directory.
  215. X * If MBX_DIR is defined, then the default mailbox is a file in that
  216. X * directory with the same name as the user.
  217. X *
  218. X * Define MBX_GROUP if all mailboxes must be owned by a specific group.
  219. X * (System V requires this feature.)  If MBX_GROUP is not defined,
  220. X * mailboxes will have their groups set to the recipients' default group.
  221. X *
  222. X * Define MBX_MODE to the file access modes for new mailboxes.
  223. X * (System V requires group write permissions, i.e. 0020.)
  224. X */
  225. X
  226. X#if defined(USG) && !defined(M_XENIX)
  227. X/* #define MBX_NAME   "mbox" */
  228. X#define MBX_DIR     "/usr/mail"
  229. X#define MBX_MODE    0660
  230. X#define MBX_GROUP   "mail"
  231. X#else
  232. X/* #define MBX_NAME   "mbox" */
  233. X#define MBX_DIR     "/usr/spool/mail"
  234. X#define MBX_MODE    0600
  235. X#endif
  236. X
  237. X/*----------------------------------------------------------------------
  238. X * Names of delivery files.
  239. X *
  240. X * SYS_DELIVER          system-wide delivery file
  241. X * POST_DELIVER         post-user delivery file
  242. X * USER_DELIVER         user delivery file (in user's home directory)
  243. X */
  244. X
  245. X#define SYS_DELIVER     "/usr/local/lib/deliver.sys"
  246. X#define POST_DELIVER    "/usr/local/lib/deliver.post"
  247. X#define USER_DELIVER    ".deliver"
  248. X
  249. X/*----------------------------------------------------------------------
  250. X * Environment variables passed to child processes.
  251. X */
  252. X
  253. X#define ENV_DFLAGS      "DELFLAGS"      /* Flags: [-[Avdt]]             */
  254. X#define ENV_SYSDEL      "SYSDELFILE"    /* System delivery file         */
  255. X#define ENV_POSTDEL     "POSTDELFILE"   /* Post-user delivery file      */
  256. X#define ENV_USERDEL     "USERDELFILE"   /* User delivery file           */
  257. X
  258. X#define ENV_HOSTNAME    "HOSTNAME"      /* Name of this host            */
  259. X#define ENV_SENDER      "SENDER"        /* Message sender               */
  260. X#define ENV_HEADER      "HEADER"        /* Message header file          */
  261. X#define ENV_BODY        "BODY"          /* Message body file            */
  262. END_OF_FILE
  263. if test 6654 -ne `wc -c <'config.h'`; then
  264.     echo shar: \"'config.h'\" unpacked with wrong size!
  265. fi
  266. # end of 'config.h'
  267. fi
  268. if test -f 'context.h' -a "${1}" != "-c" ; then 
  269.   echo shar: Will not clobber existing file \"'context.h'\"
  270. else
  271. echo shar: Extracting \"'context.h'\" \(527 characters\)
  272. sed "s/^X//" >'context.h' <<'END_OF_FILE'
  273. X/* $Header: context.h,v 2.1 89/06/09 12:25:15 network Exp $
  274. X *
  275. X * User context, as found in /etc/passwd.
  276. X *
  277. X * $Log:    context.h,v $
  278. X * Revision 2.1  89/06/09  12:25:15  network
  279. X * Update RCS revisions.
  280. X * 
  281. X * Revision 1.3  89/06/09  12:23:40  network
  282. X * Baseline for 2.0 release.
  283. X * 
  284. X */
  285. X
  286. X/*----------------------------------------------------------------------
  287. X * The context structure.
  288. X */
  289. X
  290. X#define CONTEXT struct context
  291. XCONTEXT {
  292. X    CONTEXT *ct_next;
  293. X    int     ct_uid;
  294. X    int     ct_gid;
  295. X    char    *ct_name;
  296. X    char    *ct_home;
  297. X};
  298. END_OF_FILE
  299. if test 527 -ne `wc -c <'context.h'`; then
  300.     echo shar: \"'context.h'\" unpacked with wrong size!
  301. fi
  302. # end of 'context.h'
  303. fi
  304. if test -f 'deliver.h' -a "${1}" != "-c" ; then 
  305.   echo shar: Will not clobber existing file \"'deliver.h'\"
  306. else
  307. echo shar: Extracting \"'deliver.h'\" \(3237 characters\)
  308. sed "s/^X//" >'deliver.h' <<'END_OF_FILE'
  309. X/* $Header: deliver.h,v 2.1 89/06/09 12:25:21 network Exp $
  310. X *
  311. X * General pull-it-together include file.
  312. X *
  313. X * $Log:    deliver.h,v $
  314. X * Revision 2.1  89/06/09  12:25:21  network
  315. X * Update RCS revisions.
  316. X * 
  317. X * Revision 1.10  89/06/09  12:23:44  network
  318. X * Baseline for 2.0 release.
  319. X * 
  320. X */
  321. X
  322. X#include <stdio.h>
  323. X#include <ctype.h>
  324. X#include <sys/types.h>
  325. X
  326. X#include "config.h"
  327. X#include "misc.h"
  328. X#include "context.h"
  329. X#include "dest.h"
  330. X
  331. X/*----------------------------------------------------------------------
  332. X * Global data
  333. X */
  334. X
  335. Xextern  int     verbose;        /* Print debugging messages?            */
  336. Xextern  int     dryrun;         /* Are we making a dry run?             */
  337. Xextern  int     rundfiles;      /* Run delivery files at all?           */
  338. Xextern  int     printaddrs;     /* Address resolution only?             */
  339. Xextern  int     leavetemps;     /* Leave temp files for later perusal   */
  340. Xextern  int     boxdelivery;    /* Args are mailboxes, not addresses    */
  341. Xextern  char    *sender;        /* Who is sending this message?         */
  342. X
  343. Xextern  char    *progname;      /* Name this program was invoked under  */
  344. Xextern  char    *hostname;      /* Name of this host                    */
  345. X
  346. Xextern  char    *sys_deliver;   /* Systemwide delivery file             */
  347. Xextern  char    *post_deliver;  /* Post-user delivery file              */
  348. Xextern  char    *user_deliver;  /* User delivery file                   */
  349. Xextern  char    *shell;         /* Shell used to run delivery files     */
  350. X
  351. Xextern  int     eff_uid;        /* Returned by geteuid()                */
  352. Xextern  int     eff_gid;        /* Returned by getegid()                */
  353. Xextern  int     real_uid;       /* Returned by getuid()                 */
  354. Xextern  int     real_gid;       /* Returned by getgid()                 */
  355. X
  356. Xextern  CONTEXT *eff_ct;        /* Context of effective uid             */
  357. Xextern  CONTEXT *real_ct;       /* Context of real uid                  */
  358. X
  359. Xextern  int     trust_user;     /* Do we trust the user that called us? */
  360. Xextern  int     trust_delfiles; /* Do we trust the delivery files?      */
  361. X
  362. X/* Temp file indices: */
  363. X#define T_HDR      0    /* Message header                       */
  364. X#define T_BODY     1    /* Message body                         */
  365. X#define T_HDRCOPY  2    /* Copy of message header               */
  366. X#define T_BODYCOPY 3    /* Copy of message body                 */
  367. X#define T_MAX      4    /* Number of temp files                 */
  368. X
  369. Xextern  char    *ttype[T_MAX];  /* Temp file types (for messages)       */
  370. Xextern  char    *tfile[T_MAX];  /* Temp file names                      */
  371. Xextern  char    *tenv[T_MAX];   /* Temp file environment names          */
  372. Xextern  int     tfd[T_MAX];     /* Temp file fd's                       */
  373. X
  374. Xextern  SIGFLAG got_sig;        /* We caught a signal and should exit   */
  375. X
  376. X/*----------------------------------------------------------------------
  377. X * Global functions
  378. X */
  379. X
  380. Xchar    *basename();
  381. Xchar    *gethost();
  382. Xchar    *copystr();
  383. Xchar    *derrmsg();
  384. Xchar    *zalloc();
  385. Xchar    *srealloc();
  386. X
  387. XCONTEXT *name_context();
  388. XCONTEXT *uid_context();
  389. X
  390. XFILE    *ct_popenv();
  391. Xint     ct_pclose();
  392. X
  393. XDEST    *dest();
  394. XDEST    *first_dest();
  395. XDEST    *next_dest();
  396. X
  397. Xtime_t  unctime();
  398. END_OF_FILE
  399. if test 3237 -ne `wc -c <'deliver.h'`; then
  400.     echo shar: \"'deliver.h'\" unpacked with wrong size!
  401. fi
  402. # end of 'deliver.h'
  403. fi
  404. if test -f 'dest.h' -a "${1}" != "-c" ; then 
  405.   echo shar: Will not clobber existing file \"'dest.h'\"
  406. else
  407. echo shar: Extracting \"'dest.h'\" \(2503 characters\)
  408. sed "s/^X//" >'dest.h' <<'END_OF_FILE'
  409. X/* $Header: dest.h,v 2.1 89/06/09 12:25:23 network Exp $
  410. X *
  411. X * Description of a mail destination and its state.
  412. X *
  413. X * $Log:    dest.h,v $
  414. X * Revision 2.1  89/06/09  12:25:23  network
  415. X * Update RCS revisions.
  416. X * 
  417. X * Revision 1.3  89/06/09  12:23:48  network
  418. X * Baseline for 2.0 release.
  419. X * 
  420. X */
  421. X
  422. X/*----------------------------------------------------------------------
  423. X * Destination class.
  424. X */
  425. X
  426. Xtypedef enum {
  427. X    CL_USER,                /* User name, no mailbox                */
  428. X    CL_MBOX,                /* User name, with mailbox name         */
  429. X    CL_UUCP                 /* UUCP address (bang path)             */
  430. X} DCLASS;
  431. X
  432. X/*----------------------------------------------------------------------
  433. X * Destination state.
  434. X */
  435. X
  436. Xtypedef enum {
  437. X    ST_WORKING,             /* the "normal" state                   */
  438. X    ST_HOLD,                /* on hold during expansion             */
  439. X    ST_DONE,                /* all processing complete              */
  440. X    ST_ERROR                /* "something is horribly wrong"        */
  441. X} DSTATE;
  442. X
  443. X/*----------------------------------------------------------------------
  444. X * Types of destination errors.
  445. X */
  446. X
  447. Xtypedef enum {
  448. X    E_IVADDR,               /* invalid address string               */
  449. X    E_NSUSER,               /* no such user                         */
  450. X    E_NSHOST,               /* no such host (UUCP addresses)        */
  451. X    E_CTPERM,               /* no permissions for that context      */
  452. X    E_CTLOST,               /* context lost (should never happen)   */
  453. X    E_MBOX,                 /* can't write to mailbox               */
  454. X    E_UUX                   /* can't pipe to uux                    */
  455. X} DERROR;
  456. X
  457. X/*----------------------------------------------------------------------
  458. X * Structure describing a mail destination.
  459. X */
  460. X
  461. X#define DEST    struct dest
  462. XDEST {
  463. X    DEST    *d_next;        /* next destination in the chain        */
  464. X    DEST    *d_prev;        /* previous destination in the chain    */
  465. X    DCLASS  d_class;        /* destination class                    */
  466. X    DSTATE  d_state;        /* destination state                    */
  467. X    DERROR  d_error;        /* error message (if state is ERROR)    */
  468. X    int     d_dfdone;       /* boolean -- delivery file was run     */
  469. X    char    *d_name;        /* context for delivery                 */
  470. X    char    *d_mailbox;     /* mailbox name or NULL for default     */
  471. X};
  472. X
  473. X/*----------------------------------------------------------------------
  474. X * Action macros.
  475. X */
  476. X
  477. X#define dest_err(d,m)   ((d)->d_state = ST_ERROR, (d)->d_error = (m))
  478. END_OF_FILE
  479. if test 2503 -ne `wc -c <'dest.h'`; then
  480.     echo shar: \"'dest.h'\" unpacked with wrong size!
  481. fi
  482. # end of 'dest.h'
  483. fi
  484. if test -f 'patchlevel.h' -a "${1}" != "-c" ; then 
  485.   echo shar: Will not clobber existing file \"'patchlevel.h'\"
  486. else
  487. echo shar: Extracting \"'patchlevel.h'\" \(21 characters\)
  488. sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
  489. X#define PATCHLEVEL 0
  490. END_OF_FILE
  491. if test 21 -ne `wc -c <'patchlevel.h'`; then
  492.     echo shar: \"'patchlevel.h'\" unpacked with wrong size!
  493. fi
  494. # end of 'patchlevel.h'
  495. fi
  496. if test -f 'misc.h' -a "${1}" != "-c" ; then 
  497.   echo shar: Will not clobber existing file \"'misc.h'\"
  498. else
  499. echo shar: Extracting \"'misc.h'\" \(2246 characters\)
  500. sed "s/^X//" >'misc.h' <<'END_OF_FILE'
  501. X/* $Header: misc.h,v 2.1 89/06/09 12:25:35 network Exp $
  502. X *
  503. X * Miscellaneous definitions.
  504. X *
  505. X * $Log:    misc.h,v $
  506. X * Revision 2.1  89/06/09  12:25:35  network
  507. X * Update RCS revisions.
  508. X * 
  509. X * Revision 1.7  89/06/09  12:23:56  network
  510. X * Baseline for 2.0 release.
  511. X * 
  512. X */
  513. X
  514. X/*
  515. X * Non-portable include files
  516. X */
  517. X
  518. X#ifdef USG
  519. X#include <fcntl.h>
  520. X#include <string.h>
  521. X#include <memory.h>
  522. X#endif
  523. X
  524. X#ifdef BSD
  525. X#include <strings.h>
  526. X#include <sys/file.h>
  527. X#endif
  528. X
  529. X/*
  530. X * Constants
  531. X */
  532. X
  533. X#ifdef NULL
  534. X#undef NULL
  535. X#endif
  536. X#define NULL    0               /* The One True NULL */
  537. X
  538. X#define FALSE   0
  539. X#define TRUE    1
  540. X
  541. X#ifndef O_RDONLY
  542. X#define O_RDONLY   0
  543. X#define O_WRONLY   1
  544. X#define O_RDWR     2
  545. X#endif
  546. X
  547. X/*
  548. X * Macros.
  549. X */
  550. X
  551. X/* Length parameter for fgets() on given buffer. */
  552. X
  553. X#define GETSIZE(buf)    (int) (sizeof(buf) - 1)
  554. X
  555. X/*
  556. X * Public data.
  557. X */
  558. X
  559. Xextern  char    **environ;
  560. X
  561. X/*
  562. X * Common library functions.
  563. X */
  564. X
  565. Xextern  char    *ctime();
  566. Xextern  char    *getenv();
  567. Xextern  char    *malloc();
  568. Xextern  char    *realloc();
  569. Xextern  char    *mktemp();
  570. Xextern  int     putenv();
  571. Xextern  long    lseek();
  572. Xextern  long    time();
  573. Xextern  void    free();
  574. X
  575. X#ifdef DECLARE_SIGNAL
  576. Xextern  SIGTYPE (*signal())();
  577. X#endif
  578. X
  579. X/*
  580. X * String search functions.
  581. X */
  582. X
  583. X#ifndef USG
  584. X
  585. X#ifndef BSD
  586. Xextern  char    *index();
  587. Xextern  char    *rindex();
  588. X#endif /* not BSD */
  589. X
  590. X#define strchr          index
  591. X#define strrchr         rindex
  592. X
  593. X#endif
  594. X
  595. X/*
  596. X * Memory copy and zero.
  597. X */
  598. X
  599. X#ifdef USG
  600. X#define Copy(d,s,n)     (void) memcpy(d,s,n)
  601. X#define Zero(d,n)       (void) memset(d,0,(int)(n))
  602. X#else /* not USG */
  603. X#ifdef BSD
  604. X#define Copy(d,s,n)     bcopy(s,d,n)
  605. X#define Zero(d,n)       bzero(d,n)
  606. X#else /* not BSD */
  607. X#define MEMFUNCS        /* define Copy() and Zero() in sysdep.c */
  608. X#endif /* not BSD */
  609. X#endif /* not USG */
  610. X
  611. X/*
  612. X * Line-buffering on stdio files.
  613. X */
  614. X
  615. X#ifdef USG
  616. X
  617. Xextern  int     setvbuf();
  618. X
  619. X#ifdef REVERSE_SETVBUF
  620. X#define Linebuf(f)      (void) setvbuf(f, _IOLBF, (char *)NULL, BUFSIZ)
  621. X#else
  622. X#define Linebuf(f)      (void) setvbuf(f, (char *)NULL, _IOLBF, BUFSIZ)
  623. X#endif
  624. X
  625. X#else /* not USG */
  626. X#ifdef BSD
  627. X
  628. Xextern  int     setlinebuf();
  629. X
  630. X#define Linebuf(f)      (void) setlinebuf(f)
  631. X
  632. X#else /* not BSD */
  633. X
  634. X#define Linebuf(f)      /* can't do it */
  635. X
  636. X#endif /* not BSD */
  637. X#endif /* not USG */
  638. END_OF_FILE
  639. if test 2246 -ne `wc -c <'misc.h'`; then
  640.     echo shar: \"'misc.h'\" unpacked with wrong size!
  641. fi
  642. # end of 'misc.h'
  643. fi
  644. if test -f 'context.c' -a "${1}" != "-c" ; then 
  645.   echo shar: Will not clobber existing file \"'context.c'\"
  646. else
  647. echo shar: Extracting \"'context.c'\" \(2517 characters\)
  648. sed "s/^X//" >'context.c' <<'END_OF_FILE'
  649. X/* $Header: context.c,v 2.1 89/06/09 12:25:13 network Exp $
  650. X *
  651. X * User context manager.
  652. X * This module exists for efficiency reasons; I could just call getpwnam()
  653. X * every time I need context info.
  654. X *
  655. X * $Log:    context.c,v $
  656. X * Revision 2.1  89/06/09  12:25:13  network
  657. X * Update RCS revisions.
  658. X * 
  659. X * Revision 1.5  89/06/09  12:23:39  network
  660. X * Baseline for 2.0 release.
  661. X * 
  662. X */
  663. X
  664. X#include "deliver.h"
  665. X#include <pwd.h>
  666. X#include <grp.h>
  667. X
  668. Xextern  struct passwd   *getpwnam();
  669. Xextern  struct passwd   *getpwuid();
  670. Xextern  struct group    *getgrnam();
  671. Xextern  struct group    *getgrgid();
  672. X
  673. X/*
  674. X * Local functions.
  675. X */
  676. X
  677. Xstatic  CONTEXT *new_context();
  678. X
  679. X/*
  680. X * Local data.
  681. X */
  682. X
  683. Xstatic  CONTEXT *ctlist;    /* Chain of CONTEXT structures.        */
  684. X
  685. X/*----------------------------------------------------------------------
  686. X * Look up a context by user name.
  687. X */
  688. X
  689. XCONTEXT *
  690. Xname_context(name)
  691. Xchar    *name;
  692. X{
  693. X    struct passwd *pw;
  694. X    CONTEXT *ct;
  695. X
  696. X    for (ct = ctlist; ct; ct = ct->ct_next)
  697. X    {
  698. X        if (strcmp(ct->ct_name, name) == 0)
  699. X            return ct;
  700. X    }
  701. X
  702. X    if ((pw = getpwnam(name)) == NULL)
  703. X        return NULL;
  704. X
  705. X    return new_context(pw);
  706. X}
  707. X
  708. X/*----------------------------------------------------------------------
  709. X * Look up a context by user ID.
  710. X */
  711. X
  712. XCONTEXT *
  713. Xuid_context(uid)
  714. Xint     uid;
  715. X{
  716. X    struct passwd *pw;
  717. X    CONTEXT *ct;
  718. X
  719. X    for (ct = ctlist; ct; ct = ct->ct_next)
  720. X    {
  721. X        if (ct->ct_uid == uid)
  722. X            return ct;
  723. X    }
  724. X
  725. X    if ((pw = getpwuid(uid)) == NULL)
  726. X        return NULL;
  727. X
  728. X    return new_context(pw);
  729. X}
  730. X
  731. X/*----------------------------------------------------------------------
  732. X * Local function -- create a new context structure and return
  733. X * its address.
  734. X */
  735. X
  736. Xstatic CONTEXT *
  737. Xnew_context(pw)
  738. Xstruct passwd *pw;
  739. X{
  740. X    CONTEXT *ct;
  741. X
  742. X    ct = (CONTEXT *) zalloc(sizeof(CONTEXT));
  743. X    ct->ct_uid = pw->pw_uid;
  744. X    ct->ct_gid = pw->pw_gid;
  745. X    ct->ct_name = copystr(pw->pw_name);
  746. X    ct->ct_home = copystr(pw->pw_dir);
  747. X
  748. X    ct->ct_next = ctlist;
  749. X    ctlist = ct;
  750. X
  751. X    return ct;
  752. X}
  753. X
  754. X/*----------------------------------------------------------------------
  755. X * Report whether is is possible or not to enter the given context.
  756. X */
  757. X
  758. Xint
  759. Xok_context(ct)
  760. XCONTEXT *ct;
  761. X{
  762. X    if (! ct)
  763. X        return FALSE;
  764. X
  765. X    if (eff_uid == 0
  766. X     || ((real_uid == ct->ct_uid) && (real_gid == ct->ct_gid)))
  767. X        return TRUE;
  768. X    else
  769. X        return FALSE;
  770. X}
  771. X
  772. X/*----------------------------------------------------------------------
  773. X * Look up a group ID by name.
  774. X */
  775. X
  776. X#ifdef MBX_GROUP
  777. X
  778. Xint
  779. Xgroup_id(name)
  780. Xchar    *name;
  781. X{
  782. X    struct group *grp;
  783. X
  784. X    if ((grp = getgrnam(name)) == NULL)
  785. X        return -1;
  786. X
  787. X    return grp->gr_gid;
  788. X}
  789. X
  790. X#endif /* MBX_GROUP */
  791. END_OF_FILE
  792. if test 2517 -ne `wc -c <'context.c'`; then
  793.     echo shar: \"'context.c'\" unpacked with wrong size!
  794. fi
  795. # end of 'context.c'
  796. fi
  797. if test -f 'copymsg.c' -a "${1}" != "-c" ; then 
  798.   echo shar: Will not clobber existing file \"'copymsg.c'\"
  799. else
  800. echo shar: Extracting \"'copymsg.c'\" \(8775 characters\)
  801. sed "s/^X//" >'copymsg.c' <<'END_OF_FILE'
  802. X/* $Header: copymsg.c,v 2.1 89/06/09 12:25:16 network Exp $
  803. X *
  804. X * Take the message from standard input and write it to two temp files,
  805. X * one for the header (including the empty line) and one for the body.
  806. X *
  807. X * $Log:    copymsg.c,v $
  808. X * Revision 2.1  89/06/09  12:25:16  network
  809. X * Update RCS revisions.
  810. X * 
  811. X * Revision 1.9  89/06/09  12:23:40  network
  812. X * Baseline for 2.0 release.
  813. X * 
  814. X */
  815. X
  816. X#include "deliver.h"
  817. X
  818. X/*
  819. X * Macros.
  820. X */
  821. X
  822. X/* Does a string start with "From "? */
  823. X
  824. X#define ISFROM(p) ((p)[0] == 'F' && (p)[1] == 'r' && (p)[2] == 'o' \
  825. X        && (p)[3] == 'm' && (p)[4] == ' ')
  826. X
  827. X/*
  828. X * Local functions.
  829. X */
  830. X
  831. Xstatic  char    *tempfile();
  832. Xstatic  int     tcreate();
  833. X
  834. X/*----------------------------------------------------------------------
  835. X * Copy the message on the standard input to two temp files:
  836. X * one for the header and one for the body.
  837. X */
  838. X
  839. Xint
  840. Xcopy_message()
  841. X{
  842. X    char    buf[BUFSIZ];
  843. X    FILE    *dfp[T_MAX];
  844. X    char    *p, *from_line, *fsender, *fdate, *fremote;
  845. X    int     t, b, empty_line;
  846. X    int     ret = 0;
  847. X
  848. X    /*
  849. X     * Create temporary files to hold the header and message body.
  850. X     */
  851. X
  852. X    for (t = T_HDR; t <= T_BODY; ++t)
  853. X    {
  854. X        int     fd;
  855. X
  856. X        tfile[t] = tempfile();
  857. X        if ((tfd[t] = tcreate(tfile[t])) == -1)
  858. X            return -1;
  859. X
  860. X        if ((fd = dup(tfd[t])) == -1)
  861. X        {
  862. X            syserr("dup %s fd", ttype[t]);
  863. X            return -1;
  864. X        }
  865. X        (void) lseek(fd, 0L, 0);
  866. X        if ((dfp[t] = fdopen(fd, "r+")) == NULL)
  867. X        {
  868. X            error("can't fdopen %s fd", ttype[t]);
  869. X            return -1;
  870. X        }
  871. X    }
  872. X
  873. X    /* Debugging message for later examination of temp files. */
  874. X
  875. X    if (verbose)
  876. X    {
  877. X        message("header=%s, body=%s\n",
  878. X            tfile[T_HDR], tfile[T_BODY]);
  879. X    }
  880. X
  881. X    /*
  882. X     * If there is a From_ line, find the sender name therein.
  883. X     */
  884. X
  885. X    from_line = NULL;
  886. X    fsender = fdate = fremote = NULL;
  887. X
  888. X    b = (fgets(buf, GETSIZE(buf), stdin) ? TRUE : FALSE);
  889. X
  890. X    if (b && ISFROM(buf) && (p = strchr(buf, '\n')) != NULL)
  891. X    {
  892. X        b = FALSE;
  893. X
  894. X        /* Make a mungable copy of the From_ line */
  895. X
  896. X        from_line = copystr(buf);
  897. X        if ((p = strchr(from_line, '\n')) != NULL)
  898. X            *p = 0;
  899. X
  900. X        /* Find sender */
  901. X
  902. X        p = from_line + 5;
  903. X        while (*p && isspace(*p))
  904. X            ++p;
  905. X        fsender = p;
  906. X        while (*p && !isspace(*p))
  907. X            ++p;
  908. X        if (*p)
  909. X            *p++ = 0;
  910. X
  911. X        /* Date received should be around here somewhere */
  912. X
  913. X        fdate = p;
  914. X
  915. X        /* Find 'remote from' phrase (if any) */
  916. X
  917. X        for (; (p = strchr(p, 'r')) != NULL; ++p)
  918. X        {
  919. X            if (strncmp(p, "remote from", 11) == 0)
  920. X            {
  921. X                *p = 0;
  922. X                p += 11;
  923. X                while (*p && isspace(*p))
  924. X                    ++p;
  925. X                if (*p)
  926. X                    fremote = p;
  927. X                break;
  928. X            }
  929. X        }
  930. X
  931. X        /*
  932. X         * Advance to first non-space in date.
  933. X         * If there is no date, clear the date pointer.
  934. X         */
  935. X
  936. X        while (*fdate && isspace(*fdate))
  937. X            ++fdate;
  938. X        if (*fdate == 0)
  939. X            fdate = NULL;
  940. X
  941. X        /*
  942. X         * If sender is missing, or if date is invalid,
  943. X         * we consider the entire From_ line invalid.
  944. X         */
  945. X
  946. X        if (*fsender == 0
  947. X         || (fdate != NULL && unctime(fdate) == -1) )
  948. X        {
  949. X            /* Ignore everything we found. */
  950. X
  951. X            fsender = fdate = fremote = NULL;
  952. X
  953. X            /* Print invalid From_ line in a harmless way. */
  954. X
  955. X            (void) strcpy(from_line, buf);
  956. X            (void) strcpy(buf, "Invalid-UUCP-From: ");
  957. X            (void) strcat(buf, from_line);
  958. X            b = TRUE;
  959. X        }
  960. X    }
  961. X
  962. X    /*
  963. X     * Write a From_ line to the header file.
  964. X     */
  965. X
  966. X    /* if caller specified sender, use it */
  967. X    if (sender)
  968. X        ; /* fine */
  969. X
  970. X    /* else if we found a From_ line, use it */
  971. X    else if (fsender)
  972. X    {
  973. X        if (fremote)
  974. X        {
  975. X            sender = zalloc(strlen(fremote) + sizeof("!")
  976. X                    + strlen(fsender));
  977. X            (void) sprintf(sender, "%s!%s", fremote, fsender);
  978. X        }
  979. X        else
  980. X            sender = copystr(fsender);
  981. X    }
  982. X
  983. X    /* else use our real ID */
  984. X    else
  985. X        sender = real_ct->ct_name;
  986. X
  987. X    /* debugging message */
  988. X
  989. X    if (verbose)
  990. X        message("copy_msg: sender is \"%s\"\n", sender);
  991. X
  992. X    /*
  993. X     * Finally!  Write the From_ line.
  994. X     */
  995. X
  996. X    (void) fputs("From ", dfp[T_HDR]);
  997. X    (void) fputs(sender, dfp[T_HDR]);
  998. X    (void) fputc(' ', dfp[T_HDR]);
  999. X    if (fdate)
  1000. X    {
  1001. X        (void) fputs(fdate, dfp[T_HDR]);
  1002. X        (void) fputc('\n', dfp[T_HDR]);
  1003. X    }
  1004. X    else
  1005. X    {
  1006. X        time_t  now;
  1007. X
  1008. X        (void) time(&now);
  1009. X        (void) fputs(ctime(&now), dfp[T_HDR]);
  1010. X    }
  1011. X
  1012. X    /*
  1013. X     * Free the From_ line if we allocated a copy of it.
  1014. X     */
  1015. X
  1016. X    if (from_line)
  1017. X        free(from_line);
  1018. X
  1019. X    /*
  1020. X     * Copy the rest of the header (if any).
  1021. X     */
  1022. X
  1023. X    for (; !feof(stdin) && !ferror(stdin); b = FALSE)
  1024. X    {
  1025. X        if (!b)
  1026. X        {
  1027. X            if (fgets(buf, GETSIZE(buf), stdin))
  1028. X                b = TRUE;
  1029. X            else
  1030. X                break;
  1031. X        }
  1032. X
  1033. X        /* Empty line means "end of header" */
  1034. X
  1035. X        if (buf[0] == '\n')
  1036. X        {
  1037. X            b = FALSE;    /* Don't put this line in the body. */
  1038. X            break;
  1039. X        }
  1040. X
  1041. X        /*
  1042. X         * A line too long to fit in buf[] can't be a header line.
  1043. X         * At least, that's my opinion... :-)
  1044. X         */
  1045. X
  1046. X        if (!strchr(buf, '\n'))
  1047. X            break;
  1048. X
  1049. X        /*
  1050. X         * If line begins with whitespace, it's a continuation.
  1051. X         * Else if line begins with From_ or '>', prepend '>'.
  1052. X         * Else if line doesn't look like a header, this must
  1053. X         * be the beginning of the body.
  1054. X         */
  1055. X
  1056. X        if (isspace(buf[0]))
  1057. X            ;               /* continuation */
  1058. X        else if (ISFROM(buf) || (buf[0] == '>'))
  1059. X            (void) fputc('>', dfp[T_HDR]);
  1060. X        else
  1061. X        {
  1062. X            /* look for the colon on a header label */
  1063. X
  1064. X            p = buf;
  1065. X            while (isalpha(*p) || *p == '-')
  1066. X                ++p;
  1067. X            if ((p == buf) || (*p != ':'))
  1068. X                break;  /* Not a header line! */
  1069. X        }
  1070. X
  1071. X        /* Write the line to the header file. */
  1072. X
  1073. X        (void) fputs(buf, dfp[T_HDR]);
  1074. X    }
  1075. X
  1076. X    /*
  1077. X     * End the header file with a blank line.
  1078. X     * This enables us to simply concatenate it with the body file
  1079. X     * to produce a valid message.
  1080. X     */
  1081. X
  1082. X    (void) fputc('\n', dfp[T_HDR]);
  1083. X
  1084. X    /*
  1085. X     * Copy the body (if any).
  1086. X     */
  1087. X
  1088. X    empty_line = FALSE;
  1089. X    for (; !feof(stdin) && !ferror(stdin); b = FALSE)
  1090. X    {
  1091. X        if (!b)
  1092. X        {
  1093. X            if (fgets(buf, GETSIZE(buf), stdin))
  1094. X                b = TRUE;
  1095. X            else
  1096. X                break;
  1097. X        }
  1098. X
  1099. X        if (ISFROM(buf))
  1100. X            (void) fputc('>', dfp[T_BODY]);
  1101. X        (void) fputs(buf, dfp[T_BODY]);
  1102. X
  1103. X        empty_line = (buf[0] == '\n');
  1104. X
  1105. X        /*
  1106. X         * Output the rest of a very long line.
  1107. X         * We do this here, instead of going around the loop,
  1108. X         * in order to avoid misinterpreting From_ strings
  1109. X         * that may be found in long lines.
  1110. X         */
  1111. X
  1112. X        while (!strchr(buf, '\n')
  1113. X            && !feof(stdin)
  1114. X            && !ferror(stdin)
  1115. X            && fgets(buf, GETSIZE(buf), stdin))
  1116. X            (void) fputs(buf, dfp[T_BODY]);
  1117. X    }
  1118. X
  1119. X    /* Ensure that the body ends with a blank line. */
  1120. X
  1121. X    if (! empty_line)
  1122. X        (void) fputc('\n', dfp[T_BODY]);
  1123. X
  1124. X    /*
  1125. X     * If we encountered any trouble writing to the temp files,
  1126. X     * let's not keep it secret.
  1127. X     */
  1128. X
  1129. X    for (t = T_HDR; t <= T_BODY; ++t)
  1130. X    {
  1131. X        if (ferror(dfp[t]))
  1132. X        {
  1133. X            error("error writing to %s file %s\n",
  1134. X                ttype[t], tfile[t]);
  1135. X            ret = -1;
  1136. X        }
  1137. X
  1138. X        (void) fclose(dfp[t]);
  1139. X    }
  1140. X
  1141. X    /* Return error/success. */
  1142. X
  1143. X    return ret;
  1144. X}
  1145. X
  1146. X/*----------------------------------------------------------------------
  1147. X * Create another copy of each temp file, for security reasons.
  1148. X * Also, put their names in the environment.
  1149. X */
  1150. X
  1151. Xint
  1152. Xcopy_again()
  1153. X{
  1154. X    int     r, t;
  1155. X
  1156. X    for (r = T_HDR, t = T_HDRCOPY; r <= T_BODY; ++r, ++t)
  1157. X    {
  1158. X        /*
  1159. X         * If the file exists, remove it but keep its name.
  1160. X         * Otherwise, make a new name and put that name in
  1161. X         * the environment.
  1162. X         */
  1163. X
  1164. X        if (tfile[t])
  1165. X            (void) unlink(tfile[t]);
  1166. X        else
  1167. X        {
  1168. X            tfile[t] = tempfile();
  1169. X            if (tenv[t])
  1170. X                alloc_env(tenv[t], tfile[t]);
  1171. X        }
  1172. X
  1173. X        /*
  1174. X         * Create the file and copy the contents of the
  1175. X         * original file to it.
  1176. X         */
  1177. X
  1178. X        if (tfd[t] != -1)
  1179. X            (void) close(tfd[t]);
  1180. X
  1181. X        if ((tfd[t] = tcreate(tfile[t])) == -1)
  1182. X            return -1;
  1183. X
  1184. X        (void) lseek(tfd[r], 0L, 0);
  1185. X        if (copyfd(tfd[r], tfd[t]) < 0)
  1186. X            return -1;
  1187. X    }
  1188. X
  1189. X    if (verbose)
  1190. X    {
  1191. X        message("copy_again: header to %s, body to %s\n",
  1192. X            tfile[T_HDRCOPY], tfile[T_BODYCOPY]);
  1193. X    }
  1194. X
  1195. X    return 0;
  1196. X}
  1197. X
  1198. X/*----------------------------------------------------------------------
  1199. X * Copy a file via file descriptors.
  1200. X */
  1201. X
  1202. Xint
  1203. Xcopyfd(src_fd, dest_fd)
  1204. Xint     src_fd;
  1205. Xint     dest_fd;
  1206. X{
  1207. X    char    buf[BUFSIZ];
  1208. X    int     rd, wr;
  1209. X
  1210. X    while ((rd = read(src_fd, buf, sizeof(buf))) > 0)
  1211. X    {
  1212. X        if ((wr = write(dest_fd, buf, (unsigned) rd)) != rd)
  1213. X        {
  1214. X            if (wr == -1)
  1215. X                syserr("can't write in copyfd");
  1216. X            else
  1217. X                error("write error -- disk full?\n");
  1218. X            return -1;
  1219. X        }
  1220. X    }
  1221. X
  1222. X    return 0;
  1223. X}
  1224. X
  1225. X/*----------------------------------------------------------------------
  1226. X * Return a pointer to a temporary filename, or NULL if error.
  1227. X */
  1228. X
  1229. Xstatic char *
  1230. Xtempfile()
  1231. X{
  1232. X    static char template[] = "/tmp/dl.XXXXXX";
  1233. X    char    *f;
  1234. X
  1235. X    f = zalloc(32);
  1236. X    (void) strcpy(f, template);
  1237. X    if (mktemp(f) == NULL)
  1238. X    {
  1239. X        error("can't create temporary file");
  1240. X        return NULL;
  1241. X    }
  1242. X    return f;
  1243. X}
  1244. X
  1245. X/*----------------------------------------------------------------------
  1246. X * Create a file, or complain if it doesn't work.
  1247. X */
  1248. X
  1249. Xstatic int
  1250. Xtcreate(name)
  1251. Xchar    *name;
  1252. X{
  1253. X    int     fd;
  1254. X
  1255. X#ifdef O_CREAT
  1256. X    fd = open(name, O_RDWR|O_CREAT|O_EXCL, 0);
  1257. X#else
  1258. X    fd = creat(name, 0);
  1259. X#endif
  1260. X    if (fd == -1)
  1261. X    {
  1262. X        syserr("can't create %s", name);
  1263. X        return -1;
  1264. X    }
  1265. X
  1266. X#ifndef O_CREAT
  1267. X    (void) close(fd);
  1268. X    if ((fd = open(name, 2)) == -1)
  1269. X    {
  1270. X        syserr("can't re-open %s", name);
  1271. X        return -1;
  1272. X    }
  1273. X#endif
  1274. X
  1275. X    return fd;
  1276. X}
  1277. X
  1278. END_OF_FILE
  1279. if test 8775 -ne `wc -c <'copymsg.c'`; then
  1280.     echo shar: \"'copymsg.c'\" unpacked with wrong size!
  1281. fi
  1282. # end of 'copymsg.c'
  1283. fi
  1284. echo shar: End of shell archive.
  1285. exit 0
  1286.  
  1287.  
  1288.